﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.Data.EntityClient;

namespace Net.Chirash.Twitter.TwitterDatabase
{
    public class TwitterCachingConnection : IDisposable
    {
        protected SqlCeConnection _connection;
        protected EntityConnection _entityConn;
        protected TwitterEntities _twitterEntities;
        private volatile Object __lc_ConnectionSection = new object();
        private int _cntUsingCount = 0;

        public TwitterCachingConnection()
            : this("")
        {
        }

        public TwitterCachingConnection(string connStr)
        {
            //this._connection = new SqlCeConnection(connStr);

            var entitybuilder = new EntityConnectionStringBuilder();
            entitybuilder.ProviderConnectionString = connStr;
            entitybuilder.Provider = "System.Data.SqlServerCe.3.5";
            entitybuilder.Metadata = @"res://*/TwitterModel.csdl|res://*/TwitterModel.ssdl|res://*/TwitterModel.msl";

            this._entityConn = new EntityConnection(entitybuilder.ConnectionString);
            this._twitterEntities = new TwitterEntities(this._entityConn);
        }

        public void Upgrade(string connStr)
        {
            try
            {
                using (var engine = new SqlCeEngine(connStr))
                {
                    engine.Upgrade();
                }
            }
            catch (SqlCeException) { }
            if (_connection != null)
            {
                _connection.Dispose();
            }
            _connection = new SqlCeConnection(connStr);
        }

        //public SqlCeConnection SqlCeConnection
        //{
        //    get { return this._connection; }
        //}

        public EntityConnection EntityConnection
        {
            get { return this._entityConn; }
        }

        public TwitterEntities Entities
        {
            get { return this._twitterEntities; }
        }

        private volatile object lockEntities = new object();
        public  object LockObjectForEntities
        {
            get { return this.lockEntities; }
        }

        #region Public Connection Methods

        /// <summary>
        /// Open to the connection. 
        /// </summary>
        public void Open()
        {
            lock (this.__lc_ConnectionSection)
            {
                if (this._cntUsingCount == 0)
                {
                    try
                    {
                        //this._connection.Open();
                        this._entityConn.Open();
                    }
                    catch (SqlCeInvalidDatabaseFormatException)
                    {
                        //Upgrade(this._connection.ConnectionString);
                        //this._connection.Open();
                        this._entityConn.Open();
                    }
                }
                this._cntUsingCount++;
            }
        }

        ///<summary>
        /// Close the connection.
        /// </summary>
        public void Close()
        {
            lock (this.__lc_ConnectionSection)
            {
                this._cntUsingCount--;
                if (this._cntUsingCount == 0)
                {
                    //this._connection.Close();
                    this._entityConn.Close();
                }
            }
        }

        /// <summary>
        /// Check whether the connection is open or not.
        /// If the connection is open, this property returns true; otherwise it returns false.
        /// </summary>
        //public bool IsOpen
        //{
        //    get
        //    {
        //        lock (this.__lc_ConnectionSection)
        //        {
        //            if (this._connection.State == ConnectionState.Open)
        //                return true;
        //            else
        //                return false;
        //        }
        //    }
        //}

        ///// <summary>
        ///// コネクションをOpenできるかトライします。開くことができたら、コネクションを開いた後、trueを返します。すでに開いている場合にはfalseを返します。
        ///// </summary>
        ///// <returns>コネクション開ければtrue、でなければfalse</returns>
        //public bool OpenTry()
        //{
        //    lock (this.__lc_ConnectionSection)
        //    {
        //        if (this._connection.State != ConnectionState.Open)
        //        {
        //            this._connection.Open();
        //            return true;
        //        }
        //        else
        //        {
        //            return false;
        //        }
        //    }
        //}

        #endregion

        public virtual void Dispose()
        {
            GC.SuppressFinalize(this);
            if (this._connection != null)
                this._connection.Dispose();
            if (this._entityConn != null)
                this._entityConn.Dispose();
            if (this._twitterEntities != null)
                this._twitterEntities.Dispose();
        }

        ~TwitterCachingConnection()
        {
            Dispose();
        }
    }

    public static class Extentions
    {
        public static string EscapeSqlString(this string str)
        {
            return str.Replace("'", "''").Replace(@"\", @"\\");
        }

    }
}
